﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MetaModelMember.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Defines the MetaModelMember type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.ComponentModel.Modelling
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Reflection;
    using Threading;

    public abstract class MetaModelMember
    {
        #region Fields

        private ReadOnlyCollection<Attribute> _attributes;
        private DisplayAttribute _displayAttribute;

        #endregion

        public ReadOnlyCollection<Attribute> Attributes
        {
            get
            {
                return _attributes ?? LazyInitializer.EnsureInitialized(ref _attributes, CreateAttributes);
            }
        }

        /// <summary>
        /// Gets the reflected <see cref="MemberInfo"/> the <see cref="MetaModelMember"/> is based on.
        /// </summary>
        /// <value>The reflected member.</value>
        public abstract MemberInfo ReflectedMember { get; }

        public abstract MetaModel Model { get; }

        public string Name
        {
            get { return ReflectedMember.Name; }
        }

        public string DisplayName
        {
            get { return DisplayAttribute.GetName(); }
        }

        public string DisplayDescription
        {
            get { return DisplayAttribute.GetDescription(); }
        }

        private DisplayAttribute DisplayAttribute
        {
            get 
            { 
                return _displayAttribute ?? LazyInitializer.EnsureInitialized(ref _displayAttribute, CreateDisplayAttribute); 
            }
        }

        private DisplayAttribute CreateDisplayAttribute()
        {
            return Attributes.OfType<DisplayAttribute>().FirstOrDefault() ?? new DisplayAttribute { Name = Name };
        }

        private ReadOnlyCollection<Attribute> CreateAttributes()
        {
            var list = new List<Attribute>();
            Model.AttributeProvider.InitializeAttributes(ReflectedMember, list);
            return list.AsReadOnly();
        }
    }
}